Skip to main content

aviutl2\generic\binding/
edit_section.rs

1use std::num::NonZero;
2
3use crate::common::Rational32;
4
5/// オブジェクトへのハンドル。
6#[derive(Clone, Copy, Hash, PartialEq, Eq)]
7pub struct ObjectHandle {
8    pub(crate) internal: aviutl2_sys::plugin2::OBJECT_HANDLE,
9}
10impl std::fmt::Debug for ObjectHandle {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        f.debug_tuple("ObjectHandle").field(&self.internal).finish()
13    }
14}
15impl From<aviutl2_sys::plugin2::OBJECT_HANDLE> for ObjectHandle {
16    fn from(value: aviutl2_sys::plugin2::OBJECT_HANDLE) -> Self {
17        Self { internal: value }
18    }
19}
20impl From<ObjectHandle> for aviutl2_sys::plugin2::OBJECT_HANDLE {
21    fn from(value: ObjectHandle) -> Self {
22        value.internal
23    }
24}
25
26// 動いたし、このObjectHandleをグローバルに持っておくことも想定されてそうなので多分大丈夫なはず
27unsafe impl Send for ObjectHandle {}
28unsafe impl Sync for ObjectHandle {}
29
30/// エフェクトへのハンドル。
31#[derive(Clone, Copy, Hash, PartialEq, Eq)]
32pub struct EffectHandle {
33    pub(crate) internal: aviutl2_sys::plugin2::EFFECT_HANDLE,
34}
35impl std::fmt::Debug for EffectHandle {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.debug_tuple("EffectHandle").field(&self.internal).finish()
38    }
39}
40impl From<aviutl2_sys::plugin2::EFFECT_HANDLE> for EffectHandle {
41    fn from(value: aviutl2_sys::plugin2::EFFECT_HANDLE) -> Self {
42        Self { internal: value }
43    }
44}
45impl From<EffectHandle> for aviutl2_sys::plugin2::EFFECT_HANDLE {
46    fn from(value: EffectHandle) -> Self {
47        value.internal
48    }
49}
50
51// これもある程度グローバルに持っておくことを想定されてそうなので大丈夫なはず
52unsafe impl Send for EffectHandle {}
53unsafe impl Sync for EffectHandle {}
54
55/// 編集情報構造体。
56///
57/// # Note
58///
59/// UI表示と異なり、フレーム番号・レイヤー番号は0始まりです。
60#[derive(Debug, Clone)]
61#[non_exhaustive]
62pub struct EditInfo {
63    /// シーンの幅。
64    pub width: usize,
65    /// シーンの高さ。
66    pub height: usize,
67    /// フレームレート。
68    pub fps: Rational32,
69    /// サンプルレート。
70    pub sample_rate: usize,
71    /// 現在のカーソルのフレーム番号。
72    pub frame: usize,
73    /// 現在の選択レイヤー番号。
74    pub layer: usize,
75    /// オブジェクトが存在する最大のフレーム番号。
76    pub frame_max: usize,
77    /// オブジェクトが存在する最大のレイヤー番号。
78    pub layer_max: usize,
79    /// レイヤー編集で表示されているフレーム。
80    ///
81    /// # Note
82    ///
83    /// 終了フレームは厳密な値ではありません。
84    /// フレーム数は`len()`で取得できます。
85    pub display_frame: std::ops::Range<usize>,
86    /// レイヤー編集で表示されているレイヤー。
87    ///
88    /// # Note
89    ///
90    /// 終了レイヤーは厳密な値ではありません。
91    /// レイヤー数は`len()`で取得できます。
92    pub display_layer: std::ops::Range<usize>,
93    /// フレーム範囲選択の開始フレーム番号・終了フレーム番号。
94    /// 未選択の場合は`None`になります。
95    pub select_range: Option<std::ops::RangeInclusive<usize>>,
96    /// シーンのID
97    pub scene_id: i32,
98}
99
100impl EditInfo {
101    /// # Safety
102    ///
103    /// `ptr`は有効な`EDIT_INFO`ポインタである必要があります。
104    pub unsafe fn from_raw(ptr: *const aviutl2_sys::plugin2::EDIT_INFO) -> Self {
105        let raw = unsafe { &*ptr };
106        Self {
107            width: raw.width as usize,
108            height: raw.height as usize,
109            fps: Rational32::new(raw.rate, raw.scale),
110            sample_rate: raw.sample_rate as usize,
111            frame: raw.frame as usize,
112            layer: raw.layer as usize,
113            frame_max: raw.frame_max as usize,
114            layer_max: raw.layer_max as usize,
115            display_frame: raw.display_frame_start as usize
116                ..(raw.display_frame_start + raw.display_frame_num) as usize,
117            display_layer: raw.display_layer_start as usize
118                ..(raw.display_layer_start + raw.display_layer_num) as usize,
119
120            select_range: if raw.select_range_start >= 0 && raw.select_range_end >= 0 {
121                Some(raw.select_range_start as usize..=raw.select_range_end as usize)
122            } else {
123                None
124            },
125
126            scene_id: raw.scene_id,
127        }
128    }
129}
130
131/// オブジェクトのレイヤーとフレーム情報。
132#[derive(Debug, Clone, Copy)]
133pub struct ObjectLayerFrame {
134    pub layer: usize,
135    pub start: usize,
136    pub end: usize,
137}
138
139impl ObjectLayerFrame {
140    /// フレームの範囲をRangeで取得する。
141    pub fn frame_range(&self) -> std::ops::Range<usize> {
142        self.start..(self.end + 1)
143    }
144
145    /// フレームの範囲をRangeInclusiveで取得する。
146    pub fn frame_range_inclusive(&self) -> std::ops::RangeInclusive<usize> {
147        self.start..=self.end
148    }
149}
150
151/// レイヤーとフレーム情報。
152#[derive(Debug, Clone, Copy)]
153pub struct LayerFrameData {
154    pub layer: usize,
155    pub frame: usize,
156}
157
158#[derive(Debug, Clone, Copy)]
159pub struct MediaInfo {
160    /// Videoトラック数。
161    pub video_track_num: Option<NonZero<usize>>,
162    /// Audioトラック数。
163    pub audio_track_num: Option<NonZero<usize>>,
164    /// 総時間(秒)。
165    pub total_time: f64,
166    /// 解像度の幅。
167    pub width: usize,
168    /// 解像度の高さ。
169    pub height: usize,
170}
171
172/// トラックバー情報。
173#[derive(Debug, Clone)]
174pub struct TrackInfo {
175    /// トラックバーの移動モードの名称。
176    ///  Noneの場合は移動なしです。
177    pub mode: Option<String>,
178    /// トラックバーの設定値。
179    pub params: Vec<f64>,
180    /// トラックバーの加速度が有効かどうか。
181    pub accelerate: bool,
182    /// トラックバーの減速度が有効かどうか。
183    pub decelerate: bool,
184    /// トラックバーの中間点無視が有効かどうか。
185    pub twopoint: bool,
186    /// トラックバーの時間制御が有効かどうか。
187    pub timecontrol: bool,
188    /// トラックバーグループのトラック数。
189    /// グループ化が解除されている場合は1になります。
190    pub group_num: usize,
191    /// トラックバーグループ内でのインデックス。
192    pub group_index: usize,
193    /// 所属トラックバーグループ名。
194    pub group_name: Option<String>,
195}
196
197/// パレット情報。
198#[derive(Debug, Clone, PartialEq, Eq)]
199pub struct PaletteInfo {
200    /// パレット色。
201    pub colors: [PaletteColor; Self::PALETTE_NUM],
202}
203
204impl PaletteInfo {
205    /// パレットの色数。
206    pub const PALETTE_NUM: usize = aviutl2_sys::plugin2::PALETTE_INFO::PALETTE_NUM;
207
208    fn from_raw(raw: aviutl2_sys::plugin2::PALETTE_INFO) -> Self {
209        Self {
210            colors: raw.color.map(|color| PaletteColor {
211                r: color.r,
212                g: color.g,
213                b: color.b,
214                a: color.a,
215            }),
216        }
217    }
218
219    fn to_raw(&self) -> aviutl2_sys::plugin2::PALETTE_INFO {
220        let colors: [aviutl2_sys::plugin2::PALETTE_INFO_COLOR; Self::PALETTE_NUM] = self
221            .colors
222            .iter()
223            .map(|color| aviutl2_sys::plugin2::PALETTE_INFO_COLOR {
224                r: color.r,
225                g: color.g,
226                b: color.b,
227                a: color.a,
228            })
229            .collect::<Vec<_>>()
230            .try_into()
231            .expect("PaletteInfo colors length mismatch");
232        aviutl2_sys::plugin2::PALETTE_INFO { color: colors }
233    }
234}
235
236/// パレット色。
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
238pub struct PaletteColor {
239    pub r: u8,
240    pub g: u8,
241    pub b: u8,
242    pub a: u8,
243}
244
245/// [`ReadSection::is_support_media_file`] のモード。
246#[derive(Debug, Clone, Copy)]
247pub enum MediaFileSupportMode {
248    /// 拡張子が対応しているかどうかのみを確認します。
249    ExtensionOnly,
250    /// 実際にファイルを開いて対応しているかどうかを確認します。
251    Strict,
252}
253
254/// BPM情報。
255///
256/// # Note
257///
258/// PartialOrdを実装しています。start順で並び替えられ、同じstartの場合はNoneになります。
259#[derive(Debug, Clone, Copy, PartialEq)]
260pub struct BpmInfo {
261    /// テンポ。
262    pub tempo: f32,
263    /// 拍子。
264    pub beat: i32,
265    /// 開始位置(秒)。
266    pub start: f64,
267    /// 拍子オフセット(秒)。
268    pub offset: f32,
269}
270impl PartialOrd for BpmInfo {
271    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
272        if self.start == other.start {
273            None
274        } else {
275            self.start.partial_cmp(&other.start)
276        }
277    }
278}
279impl From<aviutl2_sys::plugin2::BPM_INFO> for BpmInfo {
280    fn from(value: aviutl2_sys::plugin2::BPM_INFO) -> Self {
281        Self {
282            tempo: value.tempo,
283            beat: value.beat,
284            start: value.start,
285            offset: value.offset,
286        }
287    }
288}
289impl From<BpmInfo> for aviutl2_sys::plugin2::BPM_INFO {
290    fn from(value: BpmInfo) -> Self {
291        Self {
292            tempo: value.tempo,
293            beat: value.beat,
294            start: value.start,
295            offset: value.offset,
296        }
297    }
298}
299
300/// [`EditSection`] 関連のエラー。
301#[derive(thiserror::Error, Debug)]
302pub enum EditSectionError {
303    #[error("api call failed")]
304    ApiCallFailed,
305    #[error("object does not exist")]
306    ObjectDoesNotExist,
307    #[error("effect does not exist")]
308    EffectDoesNotExist,
309    #[error("input utf-8 string contains null byte")]
310    InputCstrContainsNull(#[from] std::ffi::NulError),
311    #[error("input utf-16 string contains null byte")]
312    InputCwstrContainsNull(#[from] crate::common::NullByteError),
313    #[error("value is out of range")]
314    ValueOutOfRange(#[from] std::num::TryFromIntError),
315    #[error("api returned non-utf8 data")]
316    NonUtf8Data(#[from] std::str::Utf8Error),
317
318    #[cfg(feature = "aviutl2-alias")]
319    #[error("alias parse error: {0}")]
320    ParseFailed(#[from] aviutl2_alias::TableParseError),
321}
322
323/// [`ReadSection::get_object_effect_item_parsed`] などのエラー。
324#[derive(thiserror::Error, Debug)]
325pub enum EditSectionParsedError<E: std::error::Error + Send + Sync + 'static> {
326    #[error(transparent)]
327    EditSectionError(#[from] EditSectionError),
328    #[error("value parse error: {0}")]
329    ParseError(E),
330}
331
332pub type EditSectionResult<T> = Result<T, EditSectionError>;
333
334/// 読み取り専用の編集セクションハンドル。
335#[derive(Debug)]
336pub struct ReadSection {
337    pub(crate) internal: *mut aviutl2_sys::plugin2::EDIT_SECTION,
338}
339
340/// 編集セクションのハンドル。
341#[derive(Debug)]
342pub struct EditSection {
343    /// 編集情報。
344    pub info: EditInfo,
345
346    pub(crate) internal: *mut aviutl2_sys::plugin2::EDIT_SECTION,
347    read_section: ReadSection,
348}
349
350impl std::ops::Deref for EditSection {
351    type Target = ReadSection;
352
353    fn deref(&self) -> &Self::Target {
354        &self.read_section
355    }
356}
357
358impl ReadSection {
359    /// 生ポインタから `ReadSection` を作成する。
360    ///
361    /// # Safety
362    ///
363    /// 有効な `EDIT_SECTION` ポインタである必要があります。
364    pub unsafe fn from_raw(ptr: *mut aviutl2_sys::plugin2::EDIT_SECTION) -> Self {
365        Self { internal: ptr }
366    }
367
368    /// 指定のフレーム番号以降にあるオブジェクトを検索する。
369    ///
370    /// # Arguments
371    ///
372    /// - `layer`:検索するレイヤー番号(0始まり)。
373    /// - `frame`:検索を開始するフレーム番号(0始まり)。
374    pub fn find_object_after(
375        &self,
376        layer: usize,
377        frame: usize,
378    ) -> EditSectionResult<Option<ObjectHandle>> {
379        let object_handle =
380            unsafe { ((*self.internal).find_object)(layer.try_into()?, frame.try_into()?) };
381        if object_handle.is_null() {
382            Ok(None)
383        } else {
384            Ok(Some(ObjectHandle {
385                internal: object_handle,
386            }))
387        }
388    }
389
390    /// オブジェクトに対象エフェクトが何個存在するかを取得する。
391    pub fn count_object_effect(
392        &self,
393        object: ObjectHandle,
394        effect: &str,
395    ) -> EditSectionResult<usize> {
396        self.ensure_object_exists(object)?;
397        let c_effect = crate::common::CWString::new(effect)?;
398        let count =
399            unsafe { ((*self.internal).count_object_effect)(object.internal, c_effect.as_ptr()) };
400        Ok(count.try_into()?)
401    }
402
403    /// 指定のオブジェクトのレイヤーとフレーム情報を取得する。
404    pub fn get_object_layer_frame(
405        &self,
406        object: ObjectHandle,
407    ) -> EditSectionResult<ObjectLayerFrame> {
408        self.ensure_object_exists(object)?;
409        let object = unsafe { ((*self.internal).get_object_layer_frame)(object.internal) };
410        Ok(ObjectLayerFrame {
411            layer: object.layer.try_into()?,
412            start: object.start.try_into()?,
413            end: object.end.try_into()?,
414        })
415    }
416
417    /// オブジェクトの情報をエイリアスデータとして取得する。
418    pub fn get_object_alias(&self, object: ObjectHandle) -> EditSectionResult<String> {
419        self.ensure_object_exists(object)?;
420        let alias_ptr = unsafe { ((*self.internal).get_object_alias)(object.internal) };
421        if alias_ptr.is_null() {
422            return Err(EditSectionError::ApiCallFailed);
423        }
424        let c_str = unsafe { std::ffi::CStr::from_ptr(alias_ptr) };
425        let alias = c_str.to_str()?.to_owned();
426        Ok(alias)
427    }
428
429    /// オブジェクトの情報をエイリアスデータとして取得し、パースする。
430    #[cfg(feature = "aviutl2-alias")]
431    pub fn get_object_alias_parsed(
432        &self,
433        object: ObjectHandle,
434    ) -> Result<aviutl2_alias::Table, EditSectionParsedError<aviutl2_alias::TableParseError>> {
435        let alias_str = self.get_object_alias(object)?;
436        let alias_data = alias_str
437            .parse()
438            .map_err(EditSectionParsedError::ParseError)?;
439        Ok(alias_data)
440    }
441
442    /// オブジェクト名を取得する。
443    pub fn get_object_name(&self, object: ObjectHandle) -> EditSectionResult<Option<String>> {
444        self.ensure_object_exists(object)?;
445        let name_ptr = unsafe { ((*self.internal).get_object_name)(object.internal) };
446        if name_ptr.is_null() {
447            return Ok(None);
448        }
449        Ok(Some(unsafe { crate::common::load_wide_string(name_ptr) }))
450    }
451
452    /// オブジェクトの設定項目の値を文字列で取得する。
453    pub fn get_object_effect_item(
454        &self,
455        object: ObjectHandle,
456        effect_name: &str,
457        effect_index: usize,
458        item: &str,
459    ) -> EditSectionResult<String> {
460        self.ensure_object_exists(object)?;
461        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
462        let c_item = crate::common::CWString::new(item)?;
463        let value_ptr = unsafe {
464            ((*self.internal).get_object_item_value)(
465                object.internal,
466                c_effect_name.as_ptr(),
467                c_item.as_ptr(),
468            )
469        };
470        if value_ptr.is_null() {
471            return Err(EditSectionError::ApiCallFailed);
472        }
473        let c_str = unsafe { std::ffi::CStr::from_ptr(value_ptr) };
474        let value = c_str.to_str()?.to_owned();
475        Ok(value)
476    }
477
478    /// オブジェクトの設定項目の値を取得し、パースする。
479    #[cfg(feature = "aviutl2-alias")]
480    pub fn get_object_effect_item_parsed<T: aviutl2_alias::FromTableValue>(
481        &self,
482        object: ObjectHandle,
483        effect_name: &str,
484        effect_index: usize,
485        item: &str,
486    ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
487    where
488        <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
489    {
490        let value_str = self.get_object_effect_item(object, effect_name, effect_index, item)?;
491        T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
492    }
493
494    /// 現在、オブジェクト設定ウィンドウで選択されているオブジェクトを取得する。
495    pub fn get_focused_object(&self) -> EditSectionResult<Option<ObjectHandle>> {
496        let object_handle = unsafe { ((*self.internal).get_focus_object)() };
497        if object_handle.is_null() {
498            Ok(None)
499        } else {
500            Ok(Some(ObjectHandle {
501                internal: object_handle,
502            }))
503        }
504    }
505
506    /// 現在選択されているオブジェクトの一覧を取得する。
507    pub fn get_selected_objects(&self) -> EditSectionResult<Vec<ObjectHandle>> {
508        let mut handles = Vec::new();
509        let num_objects = unsafe { ((*self.internal).get_selected_object_num)() };
510        for i in 0..num_objects {
511            let object_handle = unsafe { ((*self.internal).get_selected_object)(i) };
512            if object_handle.is_null() {
513                return Err(EditSectionError::ApiCallFailed);
514            }
515            handles.push(ObjectHandle {
516                internal: object_handle,
517            });
518        }
519        Ok(handles)
520    }
521
522    /// 指定のメディアファイルがサポートされているかどうか調べる。
523    pub fn is_support_media_file<P: AsRef<std::path::Path>>(
524        &self,
525        file_path: P,
526        mode: MediaFileSupportMode,
527    ) -> EditSectionResult<bool> {
528        let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
529        let is_supported = unsafe {
530            match mode {
531                MediaFileSupportMode::ExtensionOnly => {
532                    ((*self.internal).is_support_media_file)(c_file_path.as_ptr(), false)
533                }
534                MediaFileSupportMode::Strict => {
535                    ((*self.internal).is_support_media_file)(c_file_path.as_ptr(), true)
536                }
537            }
538        };
539        Ok(is_supported)
540    }
541
542    /// 指定のメディアファイルの情報を取得する。
543    pub fn get_media_info<P: AsRef<std::path::Path>>(
544        &self,
545        file_path: P,
546    ) -> EditSectionResult<MediaInfo> {
547        let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
548        let mut media_info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::MEDIA_INFO>::uninit();
549        let success = unsafe {
550            ((*self.internal).get_media_info)(
551                c_file_path.as_ptr(),
552                media_info.as_mut_ptr(),
553                std::mem::size_of::<aviutl2_sys::plugin2::MEDIA_INFO>() as i32,
554            )
555        };
556        if !success {
557            return Err(EditSectionError::ApiCallFailed);
558        }
559        let media_info = unsafe { media_info.assume_init() };
560        Ok(MediaInfo {
561            video_track_num: NonZero::new(media_info.video_track_num.try_into()?),
562            audio_track_num: NonZero::new(media_info.audio_track_num.try_into()?),
563            total_time: media_info.total_time,
564            width: media_info.width.try_into()?,
565            height: media_info.height.try_into()?,
566        })
567    }
568
569    /// レイヤーの名前を取得する。
570    pub fn get_layer_name(&self, layer: usize) -> EditSectionResult<Option<String>> {
571        let name_ptr = unsafe { ((*self.internal).get_layer_name)(layer.try_into()?) };
572        if name_ptr.is_null() {
573            return Ok(None);
574        }
575        Ok(Some(unsafe { crate::common::load_wide_string(name_ptr) }))
576    }
577
578    /// シーン名を取得する。
579    pub fn get_scene_name(&self) -> EditSectionResult<String> {
580        let name_ptr = unsafe { ((*self.internal).get_scene_name)() };
581        if name_ptr.is_null() {
582            return Err(EditSectionError::ApiCallFailed);
583        }
584        Ok(unsafe { crate::common::load_wide_string(name_ptr) })
585    }
586
587    /// レイヤーの表示・非表示を取得する。
588    pub fn get_layer_enable(&self, layer: usize) -> EditSectionResult<bool> {
589        let visible = unsafe { ((*self.internal).get_layer_enable)(layer.try_into()?) };
590        Ok(visible)
591    }
592
593    /// レイヤーのロック状態を取得する。
594    pub fn get_layer_lock(&self, layer: usize) -> EditSectionResult<bool> {
595        let locked = unsafe { ((*self.internal).get_layer_lock)(layer.try_into()?) };
596        Ok(locked)
597    }
598
599    /// オブジェクトの区間の数を取得する。
600    pub fn get_object_section_num(&self, object: ObjectHandle) -> EditSectionResult<usize> {
601        self.ensure_object_exists(object)?;
602        let count = unsafe { ((*self.internal).get_object_section_num)(object.internal) };
603        Ok(count.try_into()?)
604    }
605
606    /// オブジェクトの区間の開始フレーム番号を取得する。
607    pub fn get_object_section_frame(
608        &self,
609        object: ObjectHandle,
610        section: usize,
611    ) -> EditSectionResult<usize> {
612        self.ensure_object_exists(object)?;
613        let frame = unsafe {
614            ((*self.internal).get_object_section_frame)(object.internal, section.try_into()?)
615        };
616        if frame == -1 {
617            Err(EditSectionError::ApiCallFailed)
618        } else {
619            Ok(frame.try_into()?)
620        }
621    }
622
623    /// オブジェクトの区間のフレーム番号の一覧を取得する。
624    ///
625    /// # Note
626    ///
627    /// 終端のフレーム番号は含まれません。
628    /// 終端のフレーム番号を含めたい場合は、[`Self::get_object_section_ranges`]を使用してください。
629    pub fn get_object_section_frames(&self, object: ObjectHandle) -> EditSectionResult<Vec<usize>> {
630        self.ensure_object_exists(object)?;
631        let section_num = self.get_object_section_num(object)?;
632        let mut frames = Vec::new();
633        for section in 0..section_num {
634            frames.push(self.get_object_section_frame(object, section)?);
635        }
636        Ok(frames)
637    }
638
639    /// オブジェクトの区間のフレーム番号の範囲を取得する。
640    pub fn get_object_section_ranges(
641        &self,
642        object: ObjectHandle,
643    ) -> EditSectionResult<Vec<std::ops::Range<usize>>> {
644        self.ensure_object_exists(object)?;
645        let frames = self.get_object_section_frames(object)?;
646        let position = self.get_object_layer_frame(object)?;
647
648        Ok(frames
649            .iter()
650            .enumerate()
651            .map(|(i, &start)| {
652                let end = if i + 1 < frames.len() {
653                    frames[i + 1]
654                } else {
655                    position.end + 1
656                };
657                start..end
658            })
659            .collect())
660    }
661
662    /// 指定フレーム位置でのオブジェクトのトラックバー項目の値を取得する。
663    pub fn get_object_track_value(
664        &self,
665        object: ObjectHandle,
666        effect_name: &str,
667        effect_index: usize,
668        item: &str,
669        frame: f64,
670    ) -> EditSectionResult<f64> {
671        self.ensure_object_exists(object)?;
672        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
673        let c_item = crate::common::CWString::new(item)?;
674        let mut value = 0.0;
675        let success = unsafe {
676            ((*self.internal).get_object_track_value)(
677                object.internal,
678                c_effect_name.as_ptr(),
679                c_item.as_ptr(),
680                frame,
681                &mut value,
682            )
683        };
684        if !success {
685            return Err(EditSectionError::ApiCallFailed);
686        }
687        Ok(value)
688    }
689
690    /// 指定フレーム位置でのオブジェクトのチェックボックス項目の値を取得する。
691    pub fn get_object_check_value(
692        &self,
693        object: ObjectHandle,
694        effect_name: &str,
695        effect_index: usize,
696        item: &str,
697        frame: usize,
698    ) -> EditSectionResult<bool> {
699        self.ensure_object_exists(object)?;
700        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
701        let c_item = crate::common::CWString::new(item)?;
702        let mut value = false;
703        let success = unsafe {
704            ((*self.internal).get_object_check_value)(
705                object.internal,
706                c_effect_name.as_ptr(),
707                c_item.as_ptr(),
708                frame.try_into()?,
709                &mut value,
710            )
711        };
712        if !success {
713            return Err(EditSectionError::ApiCallFailed);
714        }
715        Ok(value)
716    }
717
718    /// オブジェクトのトラックバー項目の情報を取得する。
719    /// トラックバーではない項目の場合はエラーになります。
720    pub fn get_object_track_info(
721        &self,
722        object: ObjectHandle,
723        effect_name: &str,
724        effect_index: usize,
725        item: &str,
726    ) -> EditSectionResult<TrackInfo> {
727        self.ensure_object_exists(object)?;
728        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
729        let c_item = crate::common::CWString::new(item)?;
730        let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::TRACK_INFO>::uninit();
731        let success = unsafe {
732            ((*self.internal).get_object_track_info)(
733                object.internal,
734                c_effect_name.as_ptr(),
735                c_item.as_ptr(),
736                info.as_mut_ptr(),
737                std::mem::size_of::<aviutl2_sys::plugin2::TRACK_INFO>() as i32,
738            )
739        };
740        if !success {
741            return Err(EditSectionError::ApiCallFailed);
742        }
743
744        let info = unsafe { info.assume_init() };
745        let mode = if info.mode.is_null() {
746            None
747        } else {
748            Some(unsafe { crate::common::load_wide_string(info.mode) })
749        };
750        let param_num: usize = info.param_num.try_into()?;
751        let params = if param_num == 0 {
752            Vec::new()
753        } else {
754            if info.param.is_null() {
755                return Err(EditSectionError::ApiCallFailed);
756            }
757            unsafe { std::slice::from_raw_parts(info.param, param_num) }.to_vec()
758        };
759
760        Ok(TrackInfo {
761            mode,
762            params,
763            accelerate: info.accelerate,
764            decelerate: info.decelerate,
765            twopoint: info.twopoint,
766            timecontrol: info.timecontrol,
767            group_num: info.group_num.try_into()?,
768            group_index: info.group_index.try_into()?,
769            group_name: if info.group_name.is_null() {
770                None
771            } else {
772                Some(unsafe { crate::common::load_wide_string(info.group_name) })
773            },
774        })
775    }
776
777    /// 現在のパレット名を取得する。
778    pub fn get_palette_name(&self) -> EditSectionResult<String> {
779        let name_ptr = unsafe { ((*self.internal).get_palette_name)() };
780        if name_ptr.is_null() {
781            return Err(EditSectionError::ApiCallFailed);
782        }
783        Ok(unsafe { crate::common::load_wide_string(name_ptr) })
784    }
785
786    /// 指定のパレット情報を取得する。
787    pub fn get_palette_info(&self, name: &str) -> EditSectionResult<PaletteInfo> {
788        let c_name = crate::common::CWString::new(name)?;
789        let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::PALETTE_INFO>::uninit();
790        let success = unsafe {
791            ((*self.internal).get_palette_info)(
792                c_name.as_ptr(),
793                info.as_mut_ptr(),
794                std::mem::size_of::<aviutl2_sys::plugin2::PALETTE_INFO>() as i32,
795            )
796        };
797        if !success {
798            return Err(EditSectionError::ApiCallFailed);
799        }
800        Ok(PaletteInfo::from_raw(unsafe { info.assume_init() }))
801    }
802
803    /// 現在のパレット情報を取得する。
804    pub fn get_current_palette_info(&self) -> EditSectionResult<PaletteInfo> {
805        let name = self.get_palette_name()?;
806        self.get_palette_info(&name)
807    }
808
809    /// 登録されているフォントのDirectWriteのフォントのポインタを取得する。
810    pub fn get_font(&self, font_name: &str) -> EditSectionResult<*mut std::ffi::c_void> {
811        let c_font_name = crate::common::CWString::new(font_name)?;
812        let ptr = unsafe { ((*self.internal).get_font)(c_font_name.as_ptr()) };
813        if ptr.is_null() {
814            Err(EditSectionError::ApiCallFailed)
815        } else {
816            Ok(ptr)
817        }
818    }
819
820    /// オブジェクトのトラックバーグループの所属アイテム名を取得する。
821    pub fn get_object_track_group_names(
822        &self,
823        object: ObjectHandle,
824        effect_name: &str,
825        effect_index: usize,
826        group_name: &str,
827    ) -> EditSectionResult<Vec<String>> {
828        self.ensure_object_exists(object)?;
829        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
830        let c_group_name = crate::common::CWString::new(group_name)?;
831        let item_num = unsafe {
832            ((*self.internal).get_object_track_group_names)(
833                object.internal,
834                c_effect_name.as_ptr(),
835                c_group_name.as_ptr(),
836                std::ptr::null_mut(),
837                0,
838            )
839        };
840        let item_num: usize = item_num.try_into()?;
841        if item_num == 0 {
842            return Ok(Vec::new());
843        }
844
845        let mut item_names = vec![std::ptr::null(); item_num];
846        let actual_item_num = unsafe {
847            ((*self.internal).get_object_track_group_names)(
848                object.internal,
849                c_effect_name.as_ptr(),
850                c_group_name.as_ptr(),
851                item_names.as_mut_ptr(),
852                item_names.len().try_into()?,
853            )
854        };
855        let actual_item_num: usize = actual_item_num.try_into()?;
856        if actual_item_num > item_names.len() {
857            return Err(EditSectionError::ApiCallFailed);
858        }
859        item_names.truncate(actual_item_num);
860
861        item_names
862            .into_iter()
863            .map(|item_name| {
864                if item_name.is_null() {
865                    Err(EditSectionError::ApiCallFailed)
866                } else {
867                    Ok(unsafe { crate::common::load_wide_string(item_name) })
868                }
869            })
870            .collect()
871    }
872
873    /// 選択中オブジェクトの区間の位置を取得する。
874    pub fn get_focus_object_section(&self) -> EditSectionResult<Option<usize>> {
875        let section = unsafe { ((*self.internal).get_focus_object_section)() };
876        if section == -1 {
877            Ok(None)
878        } else {
879            Ok(Some(section.try_into()?))
880        }
881    }
882
883    /// BPMグリッドのBPM情報の一覧を取得する。
884    pub fn get_grid_bpm_list(&self) -> EditSectionResult<Vec<BpmInfo>> {
885        let mut bpm_info_list = Vec::<aviutl2_sys::plugin2::BPM_INFO>::new();
886        let bpm_size = std::mem::size_of::<aviutl2_sys::plugin2::BPM_INFO>().try_into()?;
887        let bpm_num =
888            unsafe { ((*self.internal).get_grid_bpm_list)(std::ptr::null_mut(), 0, bpm_size) };
889        if bpm_num <= 0 {
890            return Ok(vec![]);
891        }
892        bpm_info_list.resize_with(bpm_num as usize, || aviutl2_sys::plugin2::BPM_INFO {
893            tempo: 0.0,
894            beat: 0,
895            start: 0.0,
896            offset: 0.0,
897        });
898        let actual_bpm_num = unsafe {
899            ((*self.internal).get_grid_bpm_list)(
900                bpm_info_list.as_mut_ptr(),
901                bpm_info_list.len() as i32,
902                bpm_size,
903            )
904        };
905        if actual_bpm_num != bpm_num {
906            return Err(EditSectionError::ApiCallFailed);
907        }
908        let bpm_info_list = bpm_info_list.into_iter().map(BpmInfo::from).collect();
909        Ok(bpm_info_list)
910    }
911
912    /// オブジェクトからエフェクトを検索する。
913    pub fn find_effect(
914        &self,
915        object: ObjectHandle,
916        effect_name: &str,
917        effect_index: usize,
918    ) -> EditSectionResult<EffectHandle> {
919        self.ensure_object_exists(object)?;
920        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
921        let handle =
922            unsafe { ((*self.internal).find_effect)(object.internal, c_effect_name.as_ptr()) };
923        if handle.is_null() {
924            return Err(EditSectionError::ApiCallFailed);
925        }
926        Ok(EffectHandle { internal: handle })
927    }
928
929    /// オブジェクトの先頭のエフェクトを取得する。
930    pub fn get_first_effect(&self, object: ObjectHandle) -> EditSectionResult<EffectHandle> {
931        self.ensure_object_exists(object)?;
932        let handle = unsafe { ((*self.internal).find_effect)(object.internal, std::ptr::null()) };
933        if handle.is_null() {
934            // NOTE: 知っている限りでは先頭のエフェクトは常に存在するはず...
935            Err(EditSectionError::ApiCallFailed)
936        } else {
937            Ok(EffectHandle { internal: handle })
938        }
939    }
940
941    /// オブジェクトのエフェクト一覧を取得する。
942    pub fn get_effects(&self, object: ObjectHandle) -> EditSectionResult<Vec<EffectHandle>> {
943        self.ensure_object_exists(object)?;
944        let mut effects = Vec::<aviutl2_sys::plugin2::EFFECT_HANDLE>::new();
945        let num_effects =
946            unsafe { ((*self.internal).get_effect_list)(object.internal, std::ptr::null_mut(), 0) };
947        if num_effects <= 0 {
948            return Err(EditSectionError::ApiCallFailed);
949        }
950
951        effects.resize_with(num_effects as usize, std::ptr::null_mut);
952        let actual_num_effects = unsafe {
953            ((*self.internal).get_effect_list)(
954                object.internal,
955                effects.as_mut_ptr(),
956                effects.len() as i32,
957            )
958        };
959        if actual_num_effects != num_effects {
960            return Err(EditSectionError::ApiCallFailed);
961        }
962        let effect_handles = effects
963            .into_iter()
964            .map(|handle| EffectHandle { internal: handle })
965            .collect();
966        Ok(effect_handles)
967    }
968
969    /// エフェクトの有効・無効状態を取得する。
970    pub fn get_effect_enable(&self, effect: EffectHandle) -> EditSectionResult<bool> {
971        self.ensure_effect_exists(effect)?;
972        let enabled = unsafe { ((*self.internal).get_effect_enable)(effect.internal) };
973        Ok(enabled)
974    }
975
976    /// エフェクトのロック状態を取得する。
977    pub fn get_effect_lock(&self, effect: EffectHandle) -> EditSectionResult<bool> {
978        self.ensure_effect_exists(effect)?;
979        let locked = unsafe { ((*self.internal).get_effect_lock)(effect.internal) };
980        Ok(locked)
981    }
982
983    /// エフェクトの設定項目の値を文字列で取得する。
984    pub fn get_effect_item_value(
985        &self,
986        effect: EffectHandle,
987        item: &str,
988    ) -> EditSectionResult<String> {
989        self.ensure_effect_exists(effect)?;
990        let c_item = crate::common::CWString::new(item)?;
991        let value_ptr =
992            unsafe { ((*self.internal).get_effect_item_value)(effect.internal, c_item.as_ptr()) };
993        if value_ptr.is_null() {
994            return Err(EditSectionError::ApiCallFailed);
995        }
996        let c_str = unsafe { std::ffi::CStr::from_ptr(value_ptr) };
997        let value = c_str.to_str()?.to_owned();
998        Ok(value)
999    }
1000
1001    /// エフェクトの設定項目の値を取得し、パースする。
1002    #[cfg(feature = "aviutl2-alias")]
1003    pub fn get_effect_item_value_parsed<T: aviutl2_alias::FromTableValue>(
1004        &self,
1005        effect: EffectHandle,
1006        item: &str,
1007    ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
1008    where
1009        <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
1010    {
1011        let value_str = self.get_effect_item_value(effect, item)?;
1012        T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
1013    }
1014
1015    /// エフェクトの汎用データ項目のサイズを取得する。
1016    pub fn get_effect_data_size(
1017        &self,
1018        effect: EffectHandle,
1019        item: &str,
1020    ) -> EditSectionResult<usize> {
1021        self.ensure_effect_exists(effect)?;
1022        let c_item = crate::common::CWString::new(item)?;
1023        let size = unsafe {
1024            ((*self.internal).get_effect_data_value)(
1025                effect.internal,
1026                c_item.as_ptr(),
1027                std::ptr::null_mut(),
1028                0,
1029            )
1030        };
1031        Ok(size.try_into()?)
1032    }
1033
1034    /// エフェクトの汎用データ項目の値を`Vec<u8>`で取得する。
1035    pub fn get_effect_data_value(
1036        &self,
1037        effect: EffectHandle,
1038        item: &str,
1039    ) -> EditSectionResult<Vec<u8>> {
1040        self.ensure_effect_exists(effect)?;
1041        let c_item = crate::common::CWString::new(item)?;
1042        let size = self.get_effect_data_size(effect, item)?;
1043        if size == 0 {
1044            return Ok(Vec::new());
1045        }
1046        let mut buffer = vec![0u8; size];
1047        let actual_size = unsafe {
1048            ((*self.internal).get_effect_data_value)(
1049                effect.internal,
1050                c_item.as_ptr(),
1051                buffer.as_mut_ptr() as *mut std::ffi::c_void,
1052                size.try_into()?,
1053            )
1054        };
1055        if actual_size != i32::try_from(size)? {
1056            return Err(EditSectionError::ApiCallFailed);
1057        }
1058        Ok(buffer)
1059    }
1060
1061    /// エフェクトの汎用データ項目の値を指定の型で取得する。
1062    ///
1063    /// # Errors
1064    ///
1065    /// `T`
1066    /// のサイズがエフェクトのデータ項目のサイズと一致しない場合、`EditSectionError::ApiCallFailed`
1067    /// を返します。
1068    ///
1069    /// # Safety
1070    ///
1071    /// `T` は `repr(C)` であり、かつエフェクトのデータ項目のサイズと一致している必要があります。
1072    pub unsafe fn get_effect_data_value_as<T>(
1073        &self,
1074        effect: EffectHandle,
1075        item: &str,
1076    ) -> EditSectionResult<T> {
1077        let size = std::mem::size_of::<T>();
1078        let actual_size = self.get_effect_data_size(effect, item)?;
1079        if actual_size != size {
1080            return Err(EditSectionError::ApiCallFailed);
1081        }
1082        let value = unsafe {
1083            let mut value = std::mem::MaybeUninit::<T>::uninit();
1084            let actual_size = ((*self.internal).get_effect_data_value)(
1085                effect.internal,
1086                crate::common::CWString::new(item)?.as_ptr(),
1087                value.as_mut_ptr() as *mut std::ffi::c_void,
1088                size.try_into()?,
1089            );
1090            if actual_size != i32::try_from(size)? {
1091                return Err(EditSectionError::ApiCallFailed);
1092            }
1093            value.assume_init()
1094        };
1095        Ok(value)
1096    }
1097
1098    /// エフェクトの指定フレーム位置でのトラックバー項目の値を取得する。
1099    pub fn get_effect_track_value(
1100        &self,
1101        effect: EffectHandle,
1102        item: &str,
1103        frame: f64,
1104    ) -> EditSectionResult<f64> {
1105        self.ensure_effect_exists(effect)?;
1106        let c_item = crate::common::CWString::new(item)?;
1107        let mut value = 0.0;
1108        let success = unsafe {
1109            ((*self.internal).get_effect_track_value)(
1110                effect.internal,
1111                c_item.as_ptr(),
1112                frame,
1113                &mut value,
1114            )
1115        };
1116        if !success {
1117            return Err(EditSectionError::ApiCallFailed);
1118        }
1119        Ok(value)
1120    }
1121
1122    /// エフェクトの指定フレーム位置でのチェックボックス項目の値を取得する。
1123    pub fn get_effect_check_value(
1124        &self,
1125        effect: EffectHandle,
1126        item: &str,
1127        frame: usize,
1128    ) -> EditSectionResult<bool> {
1129        self.ensure_effect_exists(effect)?;
1130        let c_item = crate::common::CWString::new(item)?;
1131        let mut value = false;
1132        let success = unsafe {
1133            ((*self.internal).get_effect_check_value)(
1134                effect.internal,
1135                c_item.as_ptr(),
1136                frame.try_into()?,
1137                &mut value,
1138            )
1139        };
1140        if !success {
1141            return Err(EditSectionError::ApiCallFailed);
1142        }
1143        Ok(value)
1144    }
1145
1146    /// エフェクトのトラックバー項目の情報を取得する。
1147    pub fn get_effect_track_info(
1148        &self,
1149        effect: EffectHandle,
1150        item: &str,
1151    ) -> EditSectionResult<TrackInfo> {
1152        self.ensure_effect_exists(effect)?;
1153        let c_item = crate::common::CWString::new(item)?;
1154        let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::TRACK_INFO>::uninit();
1155        let success = unsafe {
1156            ((*self.internal).get_effect_track_info)(
1157                effect.internal,
1158                c_item.as_ptr(),
1159                info.as_mut_ptr(),
1160                std::mem::size_of::<aviutl2_sys::plugin2::TRACK_INFO>() as i32,
1161            )
1162        };
1163        if !success {
1164            return Err(EditSectionError::ApiCallFailed);
1165        }
1166
1167        let info = unsafe { info.assume_init() };
1168        let mode = if info.mode.is_null() {
1169            None
1170        } else {
1171            Some(unsafe { crate::common::load_wide_string(info.mode) })
1172        };
1173        let param_num: usize = info.param_num.try_into()?;
1174        let params = if param_num == 0 {
1175            Vec::new()
1176        } else {
1177            if info.param.is_null() {
1178                return Err(EditSectionError::ApiCallFailed);
1179            }
1180            unsafe { std::slice::from_raw_parts(info.param, param_num) }.to_vec()
1181        };
1182
1183        Ok(TrackInfo {
1184            mode,
1185            params,
1186            accelerate: info.accelerate,
1187            decelerate: info.decelerate,
1188            twopoint: info.twopoint,
1189            timecontrol: info.timecontrol,
1190            group_num: info.group_num.try_into()?,
1191            group_index: info.group_index.try_into()?,
1192            group_name: if info.group_name.is_null() {
1193                None
1194            } else {
1195                Some(unsafe { crate::common::load_wide_string(info.group_name) })
1196            },
1197        })
1198    }
1199
1200    /// エフェクト名を取得する。
1201    pub fn get_effect_name(&self, effect: EffectHandle) -> EditSectionResult<String> {
1202        let name_ptr = unsafe { ((*self.internal).get_effect_name)(effect.internal) };
1203        if name_ptr.is_null() {
1204            return Err(EditSectionError::ApiCallFailed);
1205        }
1206        Ok(unsafe { crate::common::load_wide_string(name_ptr) })
1207    }
1208
1209    /// マークされているフレームの一覧を取得する。
1210    pub fn get_mark_frame_list(&self) -> EditSectionResult<Vec<usize>> {
1211        let num_frames = unsafe { ((*self.internal).get_mark_frame_list)(std::ptr::null_mut(), 0) };
1212        if num_frames < 0 {
1213            return Err(EditSectionError::ApiCallFailed);
1214        }
1215        let num_frames = num_frames.try_into()?;
1216        let mut frames = vec![0; num_frames];
1217        let actual_num_frames = unsafe {
1218            ((*self.internal).get_mark_frame_list)(frames.as_mut_ptr(), num_frames.try_into()?)
1219        };
1220        if actual_num_frames != i32::try_from(num_frames)? {
1221            return Err(EditSectionError::ApiCallFailed);
1222        }
1223        Ok(frames
1224            .into_iter()
1225            .map(|f| f.try_into())
1226            .collect::<Result<Vec<_>, _>>()?)
1227    }
1228
1229    /// 指定フレームのマークのメモを取得する。
1230    pub fn get_mark_frame_memo(&self, frame: usize) -> EditSectionResult<String> {
1231        let c_memo_ptr = unsafe { ((*self.internal).get_mark_frame_memo)(frame.try_into()?) };
1232        if c_memo_ptr.is_null() {
1233            return Err(EditSectionError::ApiCallFailed);
1234        }
1235        let memo = unsafe { crate::common::load_wide_string(c_memo_ptr) };
1236        Ok(memo)
1237    }
1238
1239    /// オブジェクトが存在するかどうか調べる。
1240    pub fn object_exists(&self, object: ObjectHandle) -> bool {
1241        let object = unsafe { ((*self.internal).get_object_layer_frame)(object.internal) };
1242        object.layer != -1
1243    }
1244
1245    /// エフェクトが存在するかどうか調べる。
1246    pub fn effect_exists(&self, effect: EffectHandle) -> bool {
1247        let name_ptr = unsafe { ((*self.internal).get_effect_name)(effect.internal) };
1248        !name_ptr.is_null()
1249    }
1250
1251    fn ensure_object_exists(&self, object: ObjectHandle) -> EditSectionResult<()> {
1252        if !self.object_exists(object) {
1253            return Err(EditSectionError::ObjectDoesNotExist);
1254        }
1255        Ok(())
1256    }
1257
1258    fn ensure_effect_exists(&self, effect: EffectHandle) -> EditSectionResult<()> {
1259        if !self.effect_exists(effect) {
1260            return Err(EditSectionError::EffectDoesNotExist);
1261        }
1262        Ok(())
1263    }
1264
1265    /// 特定のレイヤー内のオブジェクトをイテレータで取得する。
1266    pub fn objects_in_layer(
1267        &self,
1268        layer: usize,
1269    ) -> EditSectionLayerObjectsIterator<'_, ReadSection> {
1270        EditSectionLayerObjectsIterator::new(self, layer)
1271    }
1272
1273    /// [EditSectionLayerCaller] を作成する。
1274    pub fn layer<'a>(&'a self, layer: usize) -> EditSectionLayerCaller<'a, ReadSection> {
1275        EditSectionLayerCaller::new(self, layer)
1276    }
1277
1278    /// [EditSectionObjectCaller] を作成する。
1279    pub fn object<'a>(&'a self, object: ObjectHandle) -> EditSectionObjectCaller<'a, ReadSection> {
1280        EditSectionObjectCaller::new(self, object)
1281    }
1282
1283    /// [EditSectionEffectCaller] を作成する。
1284    pub fn effect<'a>(&'a self, effect: EffectHandle) -> EditSectionEffectCaller<'a, ReadSection> {
1285        EditSectionEffectCaller::new(self, effect)
1286    }
1287}
1288
1289impl EditSection {
1290    /// 生ポインタから `EditSection` を作成する。
1291    ///
1292    /// # Safety
1293    ///
1294    /// call_edit_section から取得した、有効な `EDIT_SECTION` ポインタである必要があります。
1295    pub unsafe fn from_raw(ptr: *mut aviutl2_sys::plugin2::EDIT_SECTION) -> Self {
1296        let info = unsafe { EditInfo::from_raw((*ptr).info) };
1297        Self {
1298            internal: ptr,
1299            info,
1300            read_section: ReadSection { internal: ptr },
1301        }
1302    }
1303
1304    /// オブジェクトエイリアスから指定の位置にオブジェクトを作成する。
1305    ///
1306    /// # Arguments
1307    ///
1308    /// - `alias`:オブジェクトエイリアスのデータ。オブジェクトエイリアスと同じフォーマットで指定します。
1309    /// - `layer`:作成するオブジェクトのレイヤー番号(0始まり)。
1310    /// - `frame`:作成するオブジェクトのフレーム番号(0始まり)。
1311    /// - `length`:作成するオブジェクトの長さ(フレーム数)。
1312    ///
1313    /// lengthはエイリアスデータにフレーム情報が無い場合に利用されます。
1314    ///
1315    /// # Errors
1316    ///
1317    /// エイリアスの変換に失敗した場合、またはオブジェクトが既存のオブジェクトに重なる場合にエラー
1318    ///
1319    pub fn create_object_from_alias(
1320        &self,
1321        alias: &str,
1322        layer: usize,
1323        frame: usize,
1324        length: usize,
1325    ) -> EditSectionResult<ObjectHandle> {
1326        let c_alias = std::ffi::CString::new(alias)?;
1327        let object_handle = unsafe {
1328            ((*self.internal).create_object_from_alias)(
1329                c_alias.as_ptr(),
1330                layer.try_into()?,
1331                frame.try_into()?,
1332                length.try_into()?,
1333            )
1334        };
1335        if object_handle.is_null() {
1336            return Err(EditSectionError::ApiCallFailed);
1337        }
1338        Ok(ObjectHandle {
1339            internal: object_handle,
1340        })
1341    }
1342
1343    /// オブジェクト名を設定する。
1344    ///
1345    /// # Note
1346    ///
1347    /// `name`に`None`や空文字を指定すると、標準の名前になります。
1348    pub fn set_object_name(
1349        &self,
1350        object: ObjectHandle,
1351        name: Option<&str>,
1352    ) -> EditSectionResult<()> {
1353        self.read_section.ensure_object_exists(object)?;
1354        match name {
1355            None => {
1356                unsafe { ((*self.internal).set_object_name)(object.internal, std::ptr::null()) };
1357                Ok(())
1358            }
1359            Some(name) => {
1360                let c_name = crate::common::CWString::new(name)?;
1361                unsafe {
1362                    ((*self.internal).set_object_name)(object.internal, c_name.as_ptr());
1363                }
1364                Ok(())
1365            }
1366        }
1367    }
1368
1369    /// オブジェクトの設定項目の値を文字列で設定する。
1370    ///
1371    /// # Arguments
1372    ///
1373    /// - `object`:対象のオブジェクトハンドル。
1374    /// - `effect_name`:設定項目の名前。
1375    /// - `effect_index`:同じ名前の設定項目が複数ある場合のインデックス(0始まり)。
1376    /// - `item`:設定項目の名前。(エイリアスファイルのキーの名前)
1377    /// - `value`:設定する値。
1378    pub fn set_object_effect_item(
1379        &self,
1380        object: ObjectHandle,
1381        effect_name: &str,
1382        effect_index: usize,
1383        item: &str,
1384        value: &str,
1385    ) -> EditSectionResult<()> {
1386        self.read_section.ensure_object_exists(object)?;
1387        let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
1388        let c_item = crate::common::CWString::new(item)?;
1389        let c_value = std::ffi::CString::new(value)?;
1390        let success = unsafe {
1391            ((*self.internal).set_object_item_value)(
1392                object.internal,
1393                c_effect_name.as_ptr(),
1394                c_item.as_ptr(),
1395                c_value.as_ptr(),
1396            )
1397        };
1398        if !success {
1399            return Err(EditSectionError::ApiCallFailed);
1400        }
1401        Ok(())
1402    }
1403
1404    /// エフェクトの汎用データ項目の値をバイト列で設定する。
1405    pub fn set_effect_data_value(
1406        &self,
1407        effect: EffectHandle,
1408        item: &str,
1409        data: &[u8],
1410    ) -> EditSectionResult<()> {
1411        self.read_section.ensure_effect_exists(effect)?;
1412        let c_item = crate::common::CWString::new(item)?;
1413        let success = unsafe {
1414            ((*self.internal).set_effect_data_value)(
1415                effect.internal,
1416                c_item.as_ptr(),
1417                data.as_ptr() as *mut std::ffi::c_void,
1418                data.len().try_into()?,
1419            )
1420        };
1421        if !success {
1422            return Err(EditSectionError::ApiCallFailed);
1423        }
1424        Ok(())
1425    }
1426
1427    /// エフェクトの汎用データ項目の値を指定の型で設定する。
1428    pub fn set_effect_data_value_with<T>(
1429        &self,
1430        effect: EffectHandle,
1431        item: &str,
1432        data: &T,
1433    ) -> EditSectionResult<()> {
1434        self.read_section.ensure_effect_exists(effect)?;
1435        let c_item = crate::common::CWString::new(item)?;
1436        let success = unsafe {
1437            ((*self.internal).set_effect_data_value)(
1438                effect.internal,
1439                c_item.as_ptr(),
1440                data as *const T as *mut std::ffi::c_void,
1441                std::mem::size_of::<T>().try_into()?,
1442            )
1443        };
1444        if !success {
1445            return Err(EditSectionError::ApiCallFailed);
1446        }
1447        Ok(())
1448    }
1449
1450    /// オブジェクトを移動する。
1451    pub fn move_object(
1452        &self,
1453        object: ObjectHandle,
1454        new_layer: usize,
1455        new_start_frame: usize,
1456    ) -> EditSectionResult<()> {
1457        self.read_section.ensure_object_exists(object)?;
1458        let success = unsafe {
1459            ((*self.internal).move_object)(
1460                object.internal,
1461                new_layer.try_into()?,
1462                new_start_frame.try_into()?,
1463            )
1464        };
1465        if !success {
1466            return Err(EditSectionError::ApiCallFailed);
1467        }
1468        Ok(())
1469    }
1470
1471    /// オブジェクトを削除する。
1472    pub fn delete_object(&self, object: ObjectHandle) -> EditSectionResult<()> {
1473        self.read_section.ensure_object_exists(object)?;
1474        unsafe { ((*self.internal).delete_object)(object.internal) };
1475        Ok(())
1476    }
1477
1478    /// オブジェクト設定ウィンドウで指定のオブジェクトを選択状態にする。
1479    ///
1480    /// # Note
1481    ///
1482    /// コールバック処理の終了時に設定されます。
1483    pub fn set_focus_object(&self, object: Option<ObjectHandle>) -> EditSectionResult<()> {
1484        if let Some(object) = object {
1485            self.read_section.ensure_object_exists(object)?;
1486            unsafe { ((*self.internal).set_focus_object)(object.internal) };
1487        } else {
1488            unsafe { ((*self.internal).set_focus_object)(std::ptr::null_mut()) };
1489        }
1490        Ok(())
1491    }
1492
1493    /// プロジェクトファイルのポインタを取得する。
1494    pub fn get_project_file<'handle>(
1495        &'handle self,
1496        edit_handle: &crate::generic::EditHandle,
1497    ) -> crate::generic::ProjectFile<'handle> {
1498        let pf_ptr = unsafe { ((*self.internal).get_project_file)(edit_handle.internal) };
1499        unsafe { crate::generic::ProjectFile::from_raw(pf_ptr) }
1500    }
1501
1502    /// マウス座標のレイヤー・フレーム位置を取得する。
1503    ///
1504    /// # Returns
1505    ///
1506    /// マウスがレイヤー編集エリア内にある場合は `Some` を返し、
1507    /// そうでない場合は `None` を返します。
1508    pub fn get_mouse_layer_frame(&self) -> EditSectionResult<Option<LayerFrameData>> {
1509        let mut layer = 0;
1510        let mut frame = 0;
1511        let on_layer_edit =
1512            unsafe { ((*self.internal).get_mouse_layer_frame)(&mut layer, &mut frame) };
1513        if on_layer_edit {
1514            Ok(Some(LayerFrameData {
1515                layer: layer.try_into()?,
1516                frame: frame.try_into()?,
1517            }))
1518        } else {
1519            Ok(None)
1520        }
1521    }
1522
1523    /// 指定のスクリーン座標のレイヤー・フレーム位置を取得する。
1524    pub fn pos_to_layer_frame(&self, x: i32, y: i32) -> EditSectionResult<Option<LayerFrameData>> {
1525        let mut layer = 0;
1526        let mut frame = 0;
1527        let on_layer_edit =
1528            unsafe { ((*self.internal).pos_to_layer_frame)(x, y, &mut layer, &mut frame) };
1529        if on_layer_edit {
1530            Ok(Some(LayerFrameData {
1531                layer: layer.try_into()?,
1532                frame: frame.try_into()?,
1533            }))
1534        } else {
1535            Ok(None)
1536        }
1537    }
1538
1539    /// 指定の位置にメディアファイルからオブジェクトを作成する。
1540    ///
1541    /// # Arguments
1542    ///
1543    /// - `file_path`:メディアファイルのパス。
1544    /// - `layer`:作成するオブジェクトのレイヤー番号(0始まり)。
1545    /// - `frame`:作成するオブジェクトのフレーム番号(0始まり)。
1546    /// - `length`:作成するオブジェクトの長さ(フレーム数)。`None`を指定した場合、長さや追加位置は自動的に調整されます。
1547    pub fn create_object_from_media_file<P: AsRef<std::path::Path>>(
1548        &self,
1549        file_path: P,
1550        layer: usize,
1551        frame: usize,
1552        length: Option<usize>,
1553    ) -> EditSectionResult<ObjectHandle> {
1554        let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
1555        let object_handle = unsafe {
1556            ((*self.internal).create_object_from_media_file)(
1557                c_file_path.as_ptr(),
1558                layer.try_into()?,
1559                frame.try_into()?,
1560                length.unwrap_or(0).try_into()?,
1561            )
1562        };
1563        if object_handle.is_null() {
1564            return Err(EditSectionError::ApiCallFailed);
1565        }
1566        Ok(ObjectHandle {
1567            internal: object_handle,
1568        })
1569    }
1570
1571    /// 指定の位置にオブジェクトを作成する。
1572    ///
1573    /// # Arguments
1574    ///
1575    /// - `effect`:エフェクト名。(エイリアスファイルの effect.name の値)
1576    /// - `layer`:作成するオブジェクトのレイヤー番号(0始まり)。
1577    /// - `frame`:作成するオブジェクトのフレーム番号(0始まり)。
1578    /// - `length`:作成するオブジェクトの長さ(フレーム数)。`None`を指定した場合、長さや追加位置は自動的に調整されます。
1579    pub fn create_object(
1580        &self,
1581        effect: &str,
1582        layer: usize,
1583        frame: usize,
1584        length: Option<usize>,
1585    ) -> EditSectionResult<ObjectHandle> {
1586        let c_effect = crate::common::CWString::new(effect)?;
1587        let object_handle = unsafe {
1588            ((*self.internal).create_object)(
1589                c_effect.as_ptr(),
1590                layer.try_into()?,
1591                frame.try_into()?,
1592                length.unwrap_or(0).try_into()?,
1593            )
1594        };
1595        if object_handle.is_null() {
1596            return Err(EditSectionError::ApiCallFailed);
1597        }
1598        Ok(ObjectHandle {
1599            internal: object_handle,
1600        })
1601    }
1602
1603    /// オブジェクトにエフェクトを追加する。
1604    ///
1605    /// # Note
1606    ///
1607    /// エフェクトが入出力エフェクトの場合は、効果が追加される代わりに、オブジェクトのエフェクトが置き換えられます。
1608    ///
1609    /// # Arguments
1610    ///
1611    /// - `object`:対象のオブジェクトハンドル。
1612    /// - `effect`:追加するエフェクト名。(エイリアスファイルの effect.name の値)
1613    pub fn create_effect(
1614        &self,
1615        object: ObjectHandle,
1616        effect: &str,
1617    ) -> EditSectionResult<EffectHandle> {
1618        self.read_section.ensure_object_exists(object)?;
1619        let c_effect = crate::common::CWString::new(effect)?;
1620        let effect_handle =
1621            unsafe { ((*self.internal).create_effect)(object.internal, c_effect.as_ptr()) };
1622        if effect_handle.is_null() {
1623            return Err(EditSectionError::ApiCallFailed);
1624        }
1625        Ok(EffectHandle {
1626            internal: effect_handle,
1627        })
1628    }
1629
1630    /// オブジェクトからエフェクトを削除する。
1631    pub fn delete_effect(
1632        &self,
1633        object: ObjectHandle,
1634        effect: EffectHandle,
1635    ) -> EditSectionResult<()> {
1636        self.read_section.ensure_object_exists(object)?;
1637        self.read_section.ensure_effect_exists(effect)?;
1638        let success = unsafe { ((*self.internal).delete_effect)(object.internal, effect.internal) };
1639        if !success {
1640            return Err(EditSectionError::ApiCallFailed);
1641        }
1642        Ok(())
1643    }
1644
1645    /// オブジェクトに中間点(区間)を追加する。
1646    pub fn create_object_section(
1647        &self,
1648        object: ObjectHandle,
1649        frame: usize,
1650    ) -> EditSectionResult<()> {
1651        self.read_section.ensure_object_exists(object)?;
1652        let success =
1653            unsafe { ((*self.internal).create_object_section)(object.internal, frame.try_into()?) };
1654        if !success {
1655            return Err(EditSectionError::ApiCallFailed);
1656        }
1657        Ok(())
1658    }
1659
1660    /// オブジェクトの中間点(区間)を削除する。
1661    pub fn delete_object_section(
1662        &self,
1663        object: ObjectHandle,
1664        section: usize,
1665    ) -> EditSectionResult<()> {
1666        self.read_section.ensure_object_exists(object)?;
1667        let success = unsafe {
1668            ((*self.internal).delete_object_section)(object.internal, section.try_into()?)
1669        };
1670        if !success {
1671            return Err(EditSectionError::ApiCallFailed);
1672        }
1673        Ok(())
1674    }
1675
1676    /// オブジェクトの中間点(区間)を移動する。
1677    ///
1678    /// # Note
1679    ///
1680    /// - `section`に0を指定すると開始地点を、区間数(最終区間+1)を指定すると終了地点を移動します。
1681    /// - 区間をまたいだ移動は出来ません。
1682    pub fn move_object_section(
1683        &self,
1684        object: ObjectHandle,
1685        section: usize,
1686        new_frame: usize,
1687    ) -> EditSectionResult<()> {
1688        self.read_section.ensure_object_exists(object)?;
1689        let success = unsafe {
1690            ((*self.internal).move_object_section)(
1691                object.internal,
1692                section.try_into()?,
1693                new_frame.try_into()?,
1694            )
1695        };
1696        if !success {
1697            return Err(EditSectionError::ApiCallFailed);
1698        }
1699        Ok(())
1700    }
1701
1702    /// オブジェクトのエフェクトの順序を移動する。
1703    ///
1704    /// # Returns
1705    ///
1706    /// 移動処理後のエフェクトの順序を返します。
1707    pub fn move_effect(
1708        &self,
1709        object: ObjectHandle,
1710        effect: EffectHandle,
1711        index: usize,
1712    ) -> EditSectionResult<usize> {
1713        self.read_section.ensure_object_exists(object)?;
1714        self.read_section.ensure_effect_exists(effect)?;
1715        let success = unsafe {
1716            ((*self.internal).move_effect)(object.internal, effect.internal, index.try_into()?)
1717        };
1718        if success == -1 {
1719            return Err(EditSectionError::ApiCallFailed);
1720        }
1721        Ok(success.try_into()?)
1722    }
1723
1724    /// 現在のレイヤー・フレーム位置を設定する。
1725    ///
1726    /// # Note
1727    ///
1728    /// 設定出来る範囲に調整されます。
1729    pub fn set_cursor_layer_frame(&self, layer: usize, frame: usize) -> EditSectionResult<()> {
1730        unsafe {
1731            ((*self.internal).set_cursor_layer_frame)(layer.try_into()?, frame.try_into()?);
1732        }
1733        Ok(())
1734    }
1735
1736    /// レイヤー編集のレイヤー・フレームの表示開始位置を設定する。
1737    ///
1738    /// # Note
1739    ///
1740    /// 設定出来る範囲に調整されます。
1741    pub fn set_display_layer_frame(&self, layer: usize, frame: usize) -> EditSectionResult<()> {
1742        unsafe {
1743            ((*self.internal).set_display_layer_frame)(layer.try_into()?, frame.try_into()?);
1744        }
1745        Ok(())
1746    }
1747
1748    /// フレーム範囲選択を設定する。
1749    ///
1750    /// # Note
1751    ///
1752    /// 設定出来る範囲に調整されます。
1753    pub fn set_select_range(&self, start: usize, end: usize) -> EditSectionResult<()> {
1754        unsafe {
1755            ((*self.internal).set_select_range)(start.try_into()?, end.try_into()?);
1756        }
1757        Ok(())
1758    }
1759
1760    /// 選択されているフレーム範囲選択を解除する。
1761    pub fn clear_select_range(&self) -> EditSectionResult<()> {
1762        unsafe {
1763            ((*self.internal).set_select_range)(-1, -1);
1764        }
1765        Ok(())
1766    }
1767
1768    /// BPMグリッドのBPM情報の一覧を設定する。
1769    pub fn set_grid_bpm_list(&self, bpm_info: &[BpmInfo]) -> EditSectionResult<()> {
1770        let mut raw_bpm_info = bpm_info
1771            .iter()
1772            .copied()
1773            .map(aviutl2_sys::plugin2::BPM_INFO::from)
1774            .collect::<Vec<_>>();
1775        unsafe {
1776            ((*self.internal).set_grid_bpm_list)(
1777                raw_bpm_info.as_mut_ptr(),
1778                raw_bpm_info.len().try_into()?,
1779                std::mem::size_of::<aviutl2_sys::plugin2::BPM_INFO>().try_into()?,
1780            );
1781        }
1782        Ok(())
1783    }
1784
1785    /// レイヤーの名前を設定する。
1786    /// `name`に`None`や空文字を指定すると、標準の名前になります。
1787    pub fn set_layer_name(&self, layer: usize, name: Option<&str>) -> EditSectionResult<()> {
1788        match name {
1789            None => {
1790                unsafe { ((*self.internal).set_layer_name)(layer.try_into()?, std::ptr::null()) };
1791                Ok(())
1792            }
1793            Some(name) => {
1794                let c_name = crate::common::CWString::new(name)?;
1795                unsafe {
1796                    ((*self.internal).set_layer_name)(layer.try_into()?, c_name.as_ptr());
1797                }
1798                Ok(())
1799            }
1800        }
1801    }
1802
1803    /// シーン名を設定する。
1804    ///
1805    /// <div class="warning">
1806    /// シーンの操作は現状Undoに対応していません。
1807    /// </div>
1808    pub fn set_scene_name(&self, name: &str) -> EditSectionResult<()> {
1809        let c_name = crate::common::CWString::new(name)?;
1810        unsafe { ((*self.internal).set_scene_name)(c_name.as_ptr()) };
1811        Ok(())
1812    }
1813
1814    /// シーンの解像度を設定する。
1815    ///
1816    /// <div class="warning">
1817    /// シーンの操作は現状Undoに対応していません。
1818    /// </div>
1819    pub fn set_scene_size(&self, width: usize, height: usize) -> EditSectionResult<()> {
1820        unsafe {
1821            ((*self.internal).set_scene_size)(width.try_into()?, height.try_into()?);
1822        }
1823        Ok(())
1824    }
1825
1826    /// シーンのフレームレートを設定する。
1827    ///
1828    /// <div class="warning">
1829    /// シーンの操作は現状Undoに対応していません。
1830    /// </div>
1831    pub fn set_scene_fps(&self, fps: Rational32) -> EditSectionResult<()> {
1832        unsafe {
1833            ((*self.internal).set_scene_frame_rate)(*fps.numer(), *fps.denom());
1834        }
1835        Ok(())
1836    }
1837
1838    /// シーンのサンプルレートを設定する。
1839    ///
1840    /// <div class="warning">
1841    /// シーンの操作は現状Undoに対応していません。
1842    /// </div>
1843    pub fn set_scene_sample_rate(&self, sample_rate: usize) -> EditSectionResult<()> {
1844        unsafe {
1845            ((*self.internal).set_scene_sample_rate)(sample_rate.try_into()?);
1846        }
1847        Ok(())
1848    }
1849
1850    /// レイヤーの表示・非表示を設定する。
1851    pub fn set_layer_enable(&self, layer: usize, enable: bool) -> EditSectionResult<()> {
1852        unsafe {
1853            ((*self.internal).set_layer_enable)(layer.try_into()?, enable);
1854        }
1855        Ok(())
1856    }
1857
1858    /// レイヤーのロック状態を設定する。
1859    pub fn set_layer_lock(&self, layer: usize, lock: bool) -> EditSectionResult<()> {
1860        unsafe {
1861            ((*self.internal).set_layer_lock)(layer.try_into()?, lock);
1862        }
1863        Ok(())
1864    }
1865
1866    /// エフェクトの有効・無効状態を設定する。
1867    pub fn set_effect_enable(&self, effect: EffectHandle, enable: bool) -> EditSectionResult<()> {
1868        self.read_section.ensure_effect_exists(effect)?;
1869        unsafe {
1870            ((*self.internal).set_effect_enable)(effect.internal, enable);
1871        }
1872        Ok(())
1873    }
1874
1875    /// エフェクトのロック状態を設定する。
1876    pub fn set_effect_lock(&self, effect: EffectHandle, lock: bool) -> EditSectionResult<()> {
1877        self.read_section.ensure_effect_exists(effect)?;
1878        unsafe {
1879            ((*self.internal).set_effect_lock)(effect.internal, lock);
1880        }
1881        Ok(())
1882    }
1883
1884    /// エフェクトの設定項目の値を文字列で設定する。
1885    pub fn set_effect_item_value(
1886        &self,
1887        effect: EffectHandle,
1888        item: &str,
1889        value: &str,
1890    ) -> EditSectionResult<()> {
1891        self.read_section.ensure_effect_exists(effect)?;
1892        let c_item = crate::common::CWString::new(item)?;
1893        let c_value = std::ffi::CString::new(value)?;
1894        let success = unsafe {
1895            ((*self.internal).set_effect_item_value)(
1896                effect.internal,
1897                c_item.as_ptr(),
1898                c_value.as_ptr(),
1899            )
1900        };
1901        if !success {
1902            return Err(EditSectionError::ApiCallFailed);
1903        }
1904        Ok(())
1905    }
1906
1907    /// 指定フレームをマークする。
1908    pub fn set_mark_frame(&self, frame: usize, memo: &str) -> EditSectionResult<()> {
1909        let c_memo = crate::common::CWString::new(memo)?;
1910        unsafe {
1911            ((*self.internal).set_mark_frame)(
1912                frame.try_into()?,
1913                if memo.is_empty() {
1914                    std::ptr::null()
1915                } else {
1916                    c_memo.as_ptr()
1917                },
1918            )
1919        };
1920        Ok(())
1921    }
1922
1923    /// 指定フレームのマークを解除する。
1924    pub fn clear_mark_frame(&self, frame: usize) -> EditSectionResult<()> {
1925        unsafe { ((*self.internal).clear_mark_frame)(frame.try_into()?) };
1926        Ok(())
1927    }
1928
1929    /// 指定フレームのマークを移動する。
1930    pub fn move_mark_frame(&self, old_frame: usize, new_frame: usize) -> EditSectionResult<()> {
1931        let success = unsafe {
1932            ((*self.internal).move_mark_frame)(old_frame.try_into()?, new_frame.try_into()?)
1933        };
1934        if !success {
1935            return Err(EditSectionError::ApiCallFailed);
1936        }
1937        Ok(())
1938    }
1939
1940    /// 指定のパレット情報を設定する。
1941    pub fn set_palette_info(&self, name: &str, palette: &PaletteInfo) -> EditSectionResult<()> {
1942        let name = crate::common::CWString::new(name)?;
1943        let mut raw_palette = palette.to_raw();
1944        let success = unsafe {
1945            ((*self.internal).set_palette_info)(
1946                name.as_ptr(),
1947                &mut raw_palette as *mut aviutl2_sys::plugin2::PALETTE_INFO,
1948                std::mem::size_of::<aviutl2_sys::plugin2::PALETTE_INFO>().try_into()?,
1949            )
1950        };
1951        if !success {
1952            return Err(EditSectionError::ApiCallFailed);
1953        }
1954        Ok(())
1955    }
1956
1957    /// 編集データを編集済み状態に設定する。
1958    ///
1959    /// # Note
1960    ///
1961    /// 通常は自動的に設定されます。
1962    pub fn set_edited_state(&self) -> EditSectionResult<()> {
1963        unsafe { ((*self.internal).set_edited_state)() };
1964        Ok(())
1965    }
1966
1967    /// すべてのレイヤーをイテレータで取得する。
1968    pub fn layers(&self) -> EditSectionLayersIterator<'_> {
1969        EditSectionLayersIterator::new(self)
1970    }
1971    /// 特定のレイヤー内のオブジェクトをイテレータで取得する。
1972    pub fn objects_in_layer(
1973        &self,
1974        layer: usize,
1975    ) -> EditSectionLayerObjectsIterator<'_, EditSection> {
1976        EditSectionLayerObjectsIterator::new(self, layer)
1977    }
1978
1979    /// [EditSectionLayerCaller] を作成する。
1980    pub fn layer<'a>(&'a self, layer: usize) -> EditSectionLayerCaller<'a, EditSection> {
1981        EditSectionLayerCaller::new(self, layer)
1982    }
1983    /// [EditSectionObjectCaller] を作成する。
1984    pub fn object<'a>(&'a self, object: ObjectHandle) -> EditSectionObjectCaller<'a, EditSection> {
1985        EditSectionObjectCaller::new(self, object)
1986    }
1987
1988    /// [EditSectionEffectCaller] を作成する。
1989    pub fn effect<'a>(&'a self, effect: EffectHandle) -> EditSectionEffectCaller<'a, EditSection> {
1990        EditSectionEffectCaller::new(self, effect)
1991    }
1992}
1993
1994mod sealed {
1995    pub trait Sealed {}
1996    impl Sealed for super::ReadSection {}
1997    impl Sealed for super::EditSection {}
1998}
1999
2000pub trait ReadSectionProvider: sealed::Sealed {
2001    fn as_read_section(&self) -> &ReadSection;
2002}
2003
2004impl ReadSectionProvider for ReadSection {
2005    fn as_read_section(&self) -> &ReadSection {
2006        self
2007    }
2008}
2009
2010impl ReadSectionProvider for EditSection {
2011    fn as_read_section(&self) -> &ReadSection {
2012        &self.read_section
2013    }
2014}
2015
2016/// オブジェクト主体で関数を呼び出すための構造体。
2017/// EditSection と ObjectHandle の組をまとめ、対象オブジェクトに対する
2018/// 操作を簡潔に呼び出せるようにします。
2019pub struct EditSectionObjectCaller<'a, S: ReadSectionProvider> {
2020    edit_section: &'a S,
2021    pub handle: ObjectHandle,
2022}
2023impl<'a, S: ReadSectionProvider> EditSectionObjectCaller<'a, S> {
2024    pub fn new(edit_section: &'a S, object: ObjectHandle) -> Self {
2025        Self {
2026            edit_section,
2027            handle: object,
2028        }
2029    }
2030}
2031
2032impl<S: ReadSectionProvider> std::ops::Deref for EditSectionObjectCaller<'_, S> {
2033    type Target = ObjectHandle;
2034
2035    fn deref(&self) -> &Self::Target {
2036        &self.handle
2037    }
2038}
2039
2040impl<S> EditSectionObjectCaller<'_, S>
2041where
2042    S: ReadSectionProvider,
2043{
2044    fn read_section(&self) -> &ReadSection {
2045        self.edit_section.as_read_section()
2046    }
2047
2048    /// オブジェクトのレイヤーとフレーム情報を取得する。
2049    pub fn get_layer_frame(&self) -> EditSectionResult<ObjectLayerFrame> {
2050        self.read_section().get_object_layer_frame(self.handle)
2051    }
2052
2053    /// オブジェクトの情報をエイリアスデータとして取得する。
2054    pub fn get_alias(&self) -> EditSectionResult<String> {
2055        self.read_section().get_object_alias(self.handle)
2056    }
2057
2058    /// オブジェクトの情報をエイリアスデータとして取得し、パースする。
2059    #[cfg(feature = "aviutl2-alias")]
2060    pub fn get_alias_parsed(&self) -> EditSectionResult<aviutl2_alias::Table> {
2061        self.read_section()
2062            .get_object_alias(self.handle)?
2063            .parse()
2064            .map_err(Into::into)
2065    }
2066
2067    /// オブジェクトに対象エフェクトが何個存在するかを取得する。
2068    ///
2069    /// # Arguments
2070    ///
2071    /// - `effect`:対象のエフェクト名。(エイリアスファイルの effect.name の値)
2072    ///
2073    /// # Returns
2074    ///
2075    /// 対象エフェクトの数。存在しない場合は0を返します。
2076    pub fn count_effect(&self, effect: &str) -> EditSectionResult<usize> {
2077        self.read_section().count_object_effect(self.handle, effect)
2078    }
2079
2080    /// オブジェクトからエフェクトを検索する。
2081    pub fn find_effect(
2082        &self,
2083        effect_name: &str,
2084        effect_index: usize,
2085    ) -> EditSectionResult<EffectHandle> {
2086        self.read_section()
2087            .find_effect(self.handle, effect_name, effect_index)
2088    }
2089
2090    /// オブジェクトの先頭のエフェクトを取得する。
2091    pub fn get_first_effect(&self) -> EditSectionResult<EffectHandle> {
2092        self.read_section().get_first_effect(self.handle)
2093    }
2094
2095    /// オブジェクトのエフェクト一覧を取得する。
2096    pub fn get_effects(&self) -> EditSectionResult<Vec<EffectHandle>> {
2097        self.read_section().get_effects(self.handle)
2098    }
2099
2100    /// オブジェクトの設定項目の値を文字列で取得する。
2101    ///
2102    /// # Arguments
2103    ///
2104    /// - `effect_name`:設定項目の名前。
2105    /// - `effect_index`:同じ名前の設定項目が複数ある場合のインデックス(0始まり)。
2106    /// - `item`:設定項目の名前。(エイリアスファイルのキーの名前)
2107    pub fn get_effect_item(
2108        &self,
2109        effect_name: &str,
2110        effect_index: usize,
2111        item: &str,
2112    ) -> EditSectionResult<String> {
2113        self.read_section()
2114            .get_object_effect_item(self.handle, effect_name, effect_index, item)
2115    }
2116
2117    /// オブジェクトの設定項目の値を取得し、パースする。
2118    ///
2119    /// # See Also
2120    ///
2121    /// [`EditSectionObjectCaller::get_effect_item`]
2122    #[cfg(feature = "aviutl2-alias")]
2123    pub fn get_effect_item_parsed<T: aviutl2_alias::FromTableValue>(
2124        &self,
2125        effect_name: &str,
2126        effect_index: usize,
2127        item: &str,
2128    ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
2129    where
2130        <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
2131    {
2132        let value_str = self.get_effect_item(effect_name, effect_index, item)?;
2133        T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
2134    }
2135
2136    /// このオブジェクトが存在するかどうか調べる。
2137    pub fn exists(&self) -> bool {
2138        self.read_section().object_exists(self.handle)
2139    }
2140
2141    /// オブジェクトの名前を取得する。
2142    ///
2143    /// # Returns
2144    ///
2145    /// 標準の名前の場合は`None`を返します。
2146    pub fn get_name(&self) -> EditSectionResult<Option<String>> {
2147        self.read_section().get_object_name(self.handle)
2148    }
2149
2150    /// オブジェクトの区間の数を取得する。
2151    pub fn get_section_num(&self) -> EditSectionResult<usize> {
2152        self.read_section().get_object_section_num(self.handle)
2153    }
2154
2155    /// オブジェクトの区間の開始フレーム番号を取得する。
2156    pub fn get_section_frame(&self, section: usize) -> EditSectionResult<usize> {
2157        self.read_section()
2158            .get_object_section_frame(self.handle, section)
2159    }
2160
2161    /// オブジェクトの区間のフレーム番号の一覧を取得する。
2162    pub fn get_section_frames(&self) -> EditSectionResult<Vec<usize>> {
2163        self.read_section().get_object_section_frames(self.handle)
2164    }
2165
2166    /// 指定フレーム位置でのトラックバー項目の値を取得する。
2167    pub fn get_track_value(
2168        &self,
2169        effect_name: &str,
2170        effect_index: usize,
2171        item: &str,
2172        frame: f64,
2173    ) -> EditSectionResult<f64> {
2174        self.read_section().get_object_track_value(
2175            self.handle,
2176            effect_name,
2177            effect_index,
2178            item,
2179            frame,
2180        )
2181    }
2182
2183    /// 指定フレーム位置でのチェックボックス項目の値を取得する。
2184    pub fn get_check_value(
2185        &self,
2186        effect_name: &str,
2187        effect_index: usize,
2188        item: &str,
2189        frame: usize,
2190    ) -> EditSectionResult<bool> {
2191        self.read_section().get_object_check_value(
2192            self.handle,
2193            effect_name,
2194            effect_index,
2195            item,
2196            frame,
2197        )
2198    }
2199
2200    /// トラックバー項目の情報を取得する。
2201    pub fn get_track_info(
2202        &self,
2203        effect_name: &str,
2204        effect_index: usize,
2205        item: &str,
2206    ) -> EditSectionResult<TrackInfo> {
2207        self.read_section()
2208            .get_object_track_info(self.handle, effect_name, effect_index, item)
2209    }
2210
2211    /// オブジェクトのトラックバーグループの所属アイテム名を取得する。
2212    pub fn get_track_group_names(
2213        &self,
2214        effect_name: &str,
2215        effect_index: usize,
2216        group_name: &str,
2217    ) -> EditSectionResult<Vec<String>> {
2218        self.read_section().get_object_track_group_names(
2219            self.handle,
2220            effect_name,
2221            effect_index,
2222            group_name,
2223        )
2224    }
2225}
2226
2227impl EditSectionObjectCaller<'_, EditSection> {
2228    /// オブジェクトにエフェクトを追加する。
2229    pub fn create_effect(&self, effect: &str) -> EditSectionResult<EffectHandle> {
2230        self.edit_section.create_effect(self.handle, effect)
2231    }
2232
2233    /// オブジェクトからエフェクトを削除する。
2234    pub fn delete_effect(&self, effect: EffectHandle) -> EditSectionResult<()> {
2235        self.edit_section.delete_effect(self.handle, effect)
2236    }
2237
2238    /// オブジェクトのエフェクトの順序を移動する。
2239    pub fn move_effect(&self, effect: EffectHandle, index: usize) -> EditSectionResult<usize> {
2240        self.edit_section.move_effect(self.handle, effect, index)
2241    }
2242
2243    /// オブジェクトに中間点(区間)を追加する。
2244    pub fn create_section(&self, frame: usize) -> EditSectionResult<()> {
2245        self.edit_section.create_object_section(self.handle, frame)
2246    }
2247
2248    /// オブジェクトの中間点(区間)を削除する。
2249    pub fn delete_section(&self, section: usize) -> EditSectionResult<()> {
2250        self.edit_section
2251            .delete_object_section(self.handle, section)
2252    }
2253
2254    /// オブジェクトの中間点(区間)を移動する。
2255    ///
2256    /// 区間をまたいだ移動は出来ません。
2257    pub fn move_section(&self, section: usize, new_frame: usize) -> EditSectionResult<()> {
2258        self.edit_section
2259            .move_object_section(self.handle, section, new_frame)
2260    }
2261
2262    /// オブジェクトの設定項目の値を文字列で設定する。
2263    ///
2264    /// # Arguments
2265    ///
2266    /// - `effect_name`:設定項目の名前。
2267    /// - `effect_index`:同じ名前の設定項目が複数ある場合のインデックス(0始まり)。
2268    /// - `item`:設定項目の名前。(エイリアスファイルのキーの名前)
2269    /// - `value`:設定する値。
2270    pub fn set_effect_item(
2271        &self,
2272        effect_name: &str,
2273        effect_index: usize,
2274        item: &str,
2275        value: &str,
2276    ) -> EditSectionResult<()> {
2277        self.edit_section.set_object_effect_item(
2278            self.handle,
2279            effect_name,
2280            effect_index,
2281            item,
2282            value,
2283        )
2284    }
2285
2286    /// オブジェクトを移動する。
2287    ///
2288    /// # Arguments
2289    ///
2290    /// - `new_layer`:移動先のレイヤー番号(0始まり)。
2291    /// - `new_start_frame`:移動先の開始フレーム番号(0始まり)。
2292    pub fn move_object(&self, new_layer: usize, new_start_frame: usize) -> EditSectionResult<()> {
2293        self.edit_section
2294            .move_object(self.handle, new_layer, new_start_frame)
2295    }
2296
2297    /// オブジェクトを削除する。
2298    pub fn delete_object(&self) -> EditSectionResult<()> {
2299        self.edit_section.delete_object(self.handle)
2300    }
2301
2302    /// オブジェクト設定ウィンドウでこのオブジェクトを選択状態にする。
2303    ///
2304    /// # Note
2305    ///
2306    /// コールバック処理の終了時に設定されます。
2307    pub fn set_focus_object(&self) -> EditSectionResult<()> {
2308        self.edit_section.set_focus_object(Some(self.handle))
2309    }
2310
2311    /// オブジェクトの名前を設定する。
2312    /// `name`に`None`や空文字を指定すると、標準の名前になります。
2313    pub fn set_name(&self, name: Option<&str>) -> EditSectionResult<()> {
2314        self.edit_section.set_object_name(self.handle, name)
2315    }
2316}
2317
2318/// エフェクト主体で関数を呼び出すための構造体。
2319/// EditSection と EffectHandle の組をまとめ、対象エフェクトに対する
2320/// 操作を簡潔に呼び出せるようにします。
2321pub struct EditSectionEffectCaller<'a, S: ReadSectionProvider> {
2322    edit_section: &'a S,
2323    pub handle: EffectHandle,
2324}
2325impl<'a, S: ReadSectionProvider> EditSectionEffectCaller<'a, S> {
2326    pub fn new(edit_section: &'a S, effect: EffectHandle) -> Self {
2327        Self {
2328            edit_section,
2329            handle: effect,
2330        }
2331    }
2332}
2333
2334impl<S: ReadSectionProvider> std::ops::Deref for EditSectionEffectCaller<'_, S> {
2335    type Target = EffectHandle;
2336
2337    fn deref(&self) -> &Self::Target {
2338        &self.handle
2339    }
2340}
2341
2342impl<S> EditSectionEffectCaller<'_, S>
2343where
2344    S: ReadSectionProvider,
2345{
2346    fn read_section(&self) -> &ReadSection {
2347        self.edit_section.as_read_section()
2348    }
2349
2350    /// このエフェクトが存在するかどうか調べる。
2351    pub fn exists(&self) -> bool {
2352        self.read_section().effect_exists(self.handle)
2353    }
2354
2355    /// エフェクト名を取得する。
2356    pub fn get_name(&self) -> EditSectionResult<String> {
2357        self.read_section().get_effect_name(self.handle)
2358    }
2359
2360    /// エフェクトの有効・無効状態を取得する。
2361    pub fn get_enable(&self) -> EditSectionResult<bool> {
2362        self.read_section().get_effect_enable(self.handle)
2363    }
2364
2365    /// エフェクトのロック状態を取得する。
2366    pub fn get_lock(&self) -> EditSectionResult<bool> {
2367        self.read_section().get_effect_lock(self.handle)
2368    }
2369
2370    /// エフェクトの設定項目の値を文字列で取得する。
2371    pub fn get_item_value(&self, item: &str) -> EditSectionResult<String> {
2372        self.read_section().get_effect_item_value(self.handle, item)
2373    }
2374
2375    /// エフェクトの設定項目の値を取得し、パースする。
2376    #[cfg(feature = "aviutl2-alias")]
2377    pub fn get_item_value_parsed<T: aviutl2_alias::FromTableValue>(
2378        &self,
2379        item: &str,
2380    ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
2381    where
2382        <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
2383    {
2384        let value_str = self.get_item_value(item)?;
2385        T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
2386    }
2387
2388    /// エフェクトの汎用データ項目のサイズを取得する。
2389    pub fn get_data_size(&self, item: &str) -> EditSectionResult<usize> {
2390        self.read_section().get_effect_data_size(self.handle, item)
2391    }
2392
2393    /// エフェクトの汎用データ項目の値をバイト列で取得する。
2394    pub fn get_data_value(&self, item: &str) -> EditSectionResult<Vec<u8>> {
2395        self.read_section().get_effect_data_value(self.handle, item)
2396    }
2397
2398    /// エフェクトの汎用データ項目の値を指定の型で取得する。
2399    ///
2400    /// # Safety
2401    ///
2402    /// `T` は `repr(C)` であり、かつエフェクトのデータ項目のサイズと一致している必要があります。
2403    pub unsafe fn get_data_value_as<T>(&self, item: &str) -> EditSectionResult<T> {
2404        unsafe {
2405            self.read_section()
2406                .get_effect_data_value_as(self.handle, item)
2407        }
2408    }
2409
2410    /// 指定フレーム位置でのトラックバー項目の値を取得する。
2411    pub fn get_track_value(&self, item: &str, frame: f64) -> EditSectionResult<f64> {
2412        self.read_section()
2413            .get_effect_track_value(self.handle, item, frame)
2414    }
2415
2416    /// 指定フレーム位置でのチェックボックス項目の値を取得する。
2417    pub fn get_check_value(&self, item: &str, frame: usize) -> EditSectionResult<bool> {
2418        self.read_section()
2419            .get_effect_check_value(self.handle, item, frame)
2420    }
2421
2422    /// トラックバー項目の情報を取得する。
2423    pub fn get_track_info(&self, item: &str) -> EditSectionResult<TrackInfo> {
2424        self.read_section().get_effect_track_info(self.handle, item)
2425    }
2426}
2427
2428impl EditSectionEffectCaller<'_, EditSection> {
2429    /// エフェクトの有効・無効状態を設定する。
2430    pub fn set_enable(&self, enable: bool) -> EditSectionResult<()> {
2431        self.edit_section.set_effect_enable(self.handle, enable)
2432    }
2433
2434    /// エフェクトのロック状態を設定する。
2435    pub fn set_lock(&self, lock: bool) -> EditSectionResult<()> {
2436        self.edit_section.set_effect_lock(self.handle, lock)
2437    }
2438
2439    /// エフェクトの設定項目の値を文字列で設定する。
2440    pub fn set_item_value(&self, item: &str, value: &str) -> EditSectionResult<()> {
2441        self.edit_section
2442            .set_effect_item_value(self.handle, item, value)
2443    }
2444
2445    /// エフェクトの汎用データ項目の値をバイト列で設定する。
2446    pub fn set_data_value(&self, item: &str, data: &[u8]) -> EditSectionResult<()> {
2447        self.edit_section
2448            .set_effect_data_value(self.handle, item, data)
2449    }
2450
2451    /// エフェクトの汎用データ項目の値を指定の型で設定する。
2452    pub fn set_data_value_with<T>(&self, item: &str, data: &T) -> EditSectionResult<()> {
2453        self.edit_section
2454            .set_effect_data_value_with(self.handle, item, data)
2455    }
2456}
2457
2458/// レイヤー主体で関数を呼び出すための構造体。
2459/// EditSection と レイヤー番号 の組をまとめ、対象レイヤーに対する
2460/// 操作を簡潔に呼び出せるようにします。
2461pub struct EditSectionLayerCaller<'a, S> {
2462    edit_section: &'a S,
2463    pub index: usize,
2464}
2465impl<'a, S> EditSectionLayerCaller<'a, S> {
2466    pub fn new(edit_section: &'a S, layer: usize) -> Self {
2467        Self {
2468            edit_section,
2469            index: layer,
2470        }
2471    }
2472}
2473
2474impl<S> EditSectionLayerCaller<'_, S>
2475where
2476    S: ReadSectionProvider,
2477{
2478    fn read_section(&self) -> &ReadSection {
2479        self.edit_section.as_read_section()
2480    }
2481
2482    /// 指定のフレーム番号以降にあるオブジェクトを検索する。
2483    ///
2484    /// # Arguments
2485    ///
2486    /// - `frame`:検索を開始するフレーム番号(0始まり)。
2487    pub fn find_object_after(&self, frame: usize) -> EditSectionResult<Option<ObjectHandle>> {
2488        self.read_section().find_object_after(self.index, frame)
2489    }
2490
2491    /// レイヤーの名前を取得する。
2492    pub fn get_name(&self) -> EditSectionResult<Option<String>> {
2493        self.read_section().get_layer_name(self.index)
2494    }
2495
2496    /// レイヤーの表示・非表示を取得する。
2497    pub fn get_enable(&self) -> EditSectionResult<bool> {
2498        self.read_section().get_layer_enable(self.index)
2499    }
2500
2501    /// レイヤーのロック状態を取得する。
2502    pub fn get_lock(&self) -> EditSectionResult<bool> {
2503        self.read_section().get_layer_lock(self.index)
2504    }
2505
2506    /// このレイヤーに存在するすべてのオブジェクトを、
2507    /// 開始フレームの昇順で走査するイテレータを返す。
2508    pub fn objects(&self) -> EditSectionLayerObjectsIterator<'_, S> {
2509        EditSectionLayerObjectsIterator::new(self.edit_section, self.index)
2510    }
2511}
2512
2513impl EditSectionLayerCaller<'_, EditSection> {
2514    /// オブジェクトエイリアスから指定の位置にオブジェクトを作成する。
2515    ///
2516    /// # See Also
2517    ///
2518    /// [`EditSection::create_object_from_alias`]
2519    pub fn create_object_from_alias<P: AsRef<std::path::Path>>(
2520        &self,
2521        alias: &str,
2522        frame: usize,
2523        length: usize,
2524    ) -> EditSectionResult<ObjectHandle> {
2525        self.edit_section
2526            .create_object_from_alias(alias, self.index, frame, length)
2527    }
2528
2529    /// 指定の位置にメディアファイルからオブジェクトを作成する。
2530    ///
2531    /// # See Also
2532    ///
2533    /// [`EditSection::create_object_from_media_file`]
2534    pub fn create_object_from_media_file<P: AsRef<std::path::Path>>(
2535        &self,
2536        file_path: P,
2537        frame: usize,
2538        length: Option<usize>,
2539    ) -> EditSectionResult<ObjectHandle> {
2540        self.edit_section
2541            .create_object_from_media_file(file_path, self.index, frame, length)
2542    }
2543
2544    /// 指定の位置にオブジェクトを作成する。
2545    ///
2546    /// # See Also
2547    ///
2548    /// [`EditSection::create_object`]
2549    pub fn create_object(
2550        &self,
2551        effect: &str,
2552        frame: usize,
2553        length: Option<usize>,
2554    ) -> EditSectionResult<ObjectHandle> {
2555        self.edit_section
2556            .create_object(effect, self.index, frame, length)
2557    }
2558
2559    /// レイヤーの名前を設定する。
2560    /// `name`に`None`や空文字を指定すると、標準の名前になります。
2561    pub fn set_name(&self, name: Option<&str>) -> EditSectionResult<()> {
2562        self.edit_section.set_layer_name(self.index, name)
2563    }
2564
2565    /// レイヤーの表示・非表示を設定する。
2566    pub fn set_enable(&self, enable: bool) -> EditSectionResult<()> {
2567        self.edit_section.set_layer_enable(self.index, enable)
2568    }
2569
2570    /// レイヤーのロック状態を設定する。
2571    pub fn set_lock(&self, lock: bool) -> EditSectionResult<()> {
2572        self.edit_section.set_layer_lock(self.index, lock)
2573    }
2574}
2575
2576/// レイヤーのイテレータ。
2577#[derive(Debug, Clone)]
2578pub struct EditSectionLayersIterator<'a> {
2579    edit_section: &'a EditSection,
2580    current: usize,
2581    end: usize,
2582}
2583
2584impl<'a> EditSectionLayersIterator<'a> {
2585    fn new(edit_section: &'a EditSection) -> Self {
2586        Self {
2587            edit_section,
2588            current: 0,
2589            end: edit_section.info.layer_max.saturating_add(1),
2590        }
2591    }
2592}
2593
2594impl<'a> Iterator for EditSectionLayersIterator<'a> {
2595    type Item = EditSectionLayerCaller<'a, EditSection>;
2596
2597    fn next(&mut self) -> Option<Self::Item> {
2598        if self.current >= self.end {
2599            return None;
2600        }
2601        let layer = self.current;
2602        self.current += 1;
2603        Some(EditSectionLayerCaller::new(self.edit_section, layer))
2604    }
2605
2606    fn size_hint(&self) -> (usize, Option<usize>) {
2607        let len = self.end.saturating_sub(self.current);
2608        (len, Some(len))
2609    }
2610}
2611
2612impl<'a> DoubleEndedIterator for EditSectionLayersIterator<'a> {
2613    fn next_back(&mut self) -> Option<Self::Item> {
2614        if self.current >= self.end {
2615            return None;
2616        }
2617        self.end -= 1;
2618        Some(EditSectionLayerCaller::new(self.edit_section, self.end))
2619    }
2620}
2621
2622impl ExactSizeIterator for EditSectionLayersIterator<'_> {}
2623
2624/// レイヤー内のオブジェクトを走査するイテレータ。
2625/// アイテムは `(オブジェクトのレイヤー・フレーム情報, ハンドル)` の組です。
2626#[derive(Debug, Clone)]
2627pub struct EditSectionLayerObjectsIterator<'a, S> {
2628    edit_section: &'a S,
2629    layer: usize,
2630    next_frame: usize,
2631}
2632
2633impl<'a, S> EditSectionLayerObjectsIterator<'a, S> {
2634    fn new(edit_section: &'a S, layer: usize) -> Self {
2635        Self {
2636            edit_section,
2637            layer,
2638            next_frame: 0,
2639        }
2640    }
2641}
2642
2643impl<S> Iterator for EditSectionLayerObjectsIterator<'_, S>
2644where
2645    S: ReadSectionProvider,
2646{
2647    type Item = (ObjectLayerFrame, ObjectHandle);
2648
2649    fn next(&mut self) -> Option<Self::Item> {
2650        let read_section = self.edit_section.as_read_section();
2651        // 検索・取得でエラーが出た場合は None を返して終了する。
2652        let Ok(Some(handle)) = read_section.find_object_after(self.layer, self.next_frame) else {
2653            return None;
2654        };
2655
2656        let lf = match read_section.get_object_layer_frame(handle) {
2657            Ok(lf) => lf,
2658            Err(_) => return None,
2659        };
2660
2661        // 次の検索開始位置を、いま見つかったオブジェクトの末尾+1 に進める。
2662        self.next_frame = lf.end.saturating_add(1);
2663
2664        Some((lf, handle))
2665    }
2666}
2667
2668fn effect_key(effect_name: &str, effect_index: usize) -> String {
2669    format!("{effect_name}:{effect_index}")
2670}